<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>十字路口堵塞过程</title>
		<style type="text/css">
			canvas {
				width: 800px;
				height: 600px;
				border: 1px solid #000000;
			}

			.div-controls {
				margin-bottom: 20px;
			}

			button {
				width: 120px;
				height: 30px;
			}
		</style>
		<script type="text/javascript">
			let W = 800;
			let H = 600;
			let isRun = false;
			let ctx;
			let spirits;
			let road;
			let timerId;
			class Road {
				constructor() {
					this.myWidth = 40;
					this.myHeight = 40;
					this.lastCars = [];
				}
				createCar() {
					for (let i = 0; i < 4; i++) {
						let car = this.lastCars[i];
						if ((car == null ||
								i == 0 && car.x > car.myWidth + 10 ||
								i == 1 && car.y < H - car.myHeight - 10 ||
								i == 2 && car.x < W - car.myWidth - 10 ||
								i == 3 && car.y > car.myHeight + 10) &&
							Math.round(Math.random() * 10000) % 30 == 0) {
							let deg = i * 90;
							car = new Car(deg);
							switch (i) {
								case 0:
									car.x = 0
									car.y = H / 2 + road.myWidth / 2;
									break;
								case 1:
									car.x = W / 2 + road.myWidth / 2;
									car.y = H;
									break;
								case 2:
									car.x = W;
									car.y = H / 2 - road.myWidth / 2;
									break;
								case 3:
									car.x = W / 2 - road.myWidth / 2;
									car.y = 0;
									break;
							}
							this.lastCars[i] = car;
							spirits.push(car);
						}
					}
				}
				render() {
					this.createCar();
					//
					ctx.strokeStyle = "#000000";
					ctx.lineWidth = 1;
					//
					let x = W / 2 - this.myWidth - 0.5;
					let y = 0;
					ctx.moveTo(x, y);
					ctx.lineTo(x, H);
					x += this.myWidth;
					ctx.moveTo(x, y);
					ctx.lineTo(x, H);
					x += this.myWidth;
					ctx.moveTo(x, y);
					ctx.lineTo(x, H);
					//
					x = 0;
					y = H / 2 - this.myWidth - 0.5;
					ctx.moveTo(x, y);
					ctx.lineTo(W, y);
					y += this.myWidth;
					ctx.moveTo(x, y);
					ctx.lineTo(W, y);
					y += this.myWidth;
					ctx.moveTo(x, y);
					ctx.lineTo(W, y);
					//
					ctx.stroke();
					//
					x = W / 2 - this.myWidth - 0.5;
					y = H / 2 - this.myWidth - 0.5;
					ctx.fillStyle = "white";
					ctx.fillRect(x, y, this.myWidth * 2, this.myWidth * 2);
				}
			}
			class Car {
				constructor(degree) {
					this.myWidth = 50;
					this.myHeight = 34;
					this.x = 0;
					this.y = 0;
					this.degree = degree;
					this.v = 5;
				}
				move(type) {
					let radian = this.degree * Math.PI / 180;
					// console.log('radian=', radian)
					let x0 = this.x;
					let y0 = this.y;
					if (type == 'back') {
						this.x = this.x0;
						this.y = this.y0;
					} else {
						this.x0 = this.x;
						this.y0 = this.y;
						this.x = this.x + this.v * Math.cos(radian);
						this.y = this.y - this.v * Math.sin(radian);
					}
					//
					if (this.x + 100 < 0 ||
						this.x - 100 > W ||
						this.y + 100 < 0 ||
						this.y - 100 > H) {
						this.destroy = true;
					}
					//
					this.x1 = this.x - this.myHeight / 2 * Math.sin(radian);
					this.y1 = this.y - this.myHeight / 2 * Math.cos(radian);
					this.x2 = this.x1 + this.myHeight * Math.sin(radian);
					this.y2 = this.y1 + this.myHeight * Math.cos(radian);
					this.x3 = this.x2 - this.myWidth * Math.cos(radian);
					this.y3 = this.y2 + this.myWidth * Math.sin(radian);
					this.x4 = this.x3 - this.myHeight * Math.sin(radian);
					this.y4 = this.y3 - this.myHeight * Math.cos(radian);
					//
					if (type != 'back' && !this.destroy && this.collide()) {
						// console.log('collide');
						this.move('back');
					}
				}
				getRange() {
					return {
						x: this.x3 - (this.x3 - this.x1) / 2,
						y: this.y3 - (this.y3 - this.y1) / 2,
						w: Math.abs(this.x3 - this.x1) + 2,
						h: Math.abs(this.y3 - this.y1) + 2
					};
				}
				collide() {
					for (let i = 0; i < spirits.length; i++) {
						let item = spirits[i];
						if (item instanceof Car && item != this) {
							let r1 = this.getRange();
							let r2 = item.getRange();
							if (
								Math.abs(r1.x - r2.x) < r1.w / 2 + r2.w / 2 &&
								Math.abs(r1.y - r2.y) < r1.h / 2 + r2.h / 2
							) {
								return true;
							}
						}
					}
					return false;
				}
				render() {
					ctx.strokeStyle = "steelblue"; //sandybrown
					ctx.fillStyle = "steelblue";
					ctx.lineWidth = 1;
					//
					//
					this.move();
					//
					ctx.strokeStyle = "steelblue"; //sandybrown
					ctx.fillStyle = "steelblue";
					ctx.lineWidth = 1;
					//
					/*
					console.log('p0', this.x, this.y);
					console.log('p1', this.x1, this.y1);
					console.log('p2', this.x2, this.y2);
					console.log('p3', this.x3, this.y3);
					console.log('p4', this.x4, this.y4);
					*/
					ctx.beginPath();
					ctx.moveTo(this.x1, this.y1);
					ctx.lineTo(this.x2, this.y2);
					ctx.lineTo(this.x3, this.y3);
					ctx.lineTo(this.x4, this.y4);
					ctx.closePath();
					ctx.fill();
					ctx.fillStyle = "palevioletred";
					ctx.beginPath();
					ctx.arc(this.x, this.y, 4, 0, Math.PI * 2, true);
					ctx.closePath();
					ctx.fill();
					// console.log('画车', this.x1, this.y1, this.myWidth, this.myHeight)
				}
			}

			function initial() {
				spirits = [];
				road = new Road();
				spirits.push(road);
				let car;
				/*
				car = new Car(0);
				car.x = 0
				car.y = H / 2 + road.myWidth / 2;
				spirits.push(car);

				car = new Car(180);
				car.x = W;
				car.y = H / 2 - road.myWidth / 2;
				spirits.push(car);

				car = new Car(90);
				car.x = W / 2 + road.myWidth / 2;
				car.y = H;
				spirits.push(car);

				car = new Car(270);
				car.x = W / 2 - road.myWidth / 2;
				car.y = 0;
				spirits.push(car);
				*/
			}

			function render() {
				if (!isRun) {
					return;
				}
				ctx.clearRect(0, 0, 800, 600);
				for (let i = 0; i < spirits.length; i++) {
					let item = spirits[i];
					item.render();
					if (item.destroy) {
						spirits.splice(i, 1);
						i--;
					}
				}
				if (spirits.oldLength && spirits.oldLength > 1 && spirits.length <= 1) {
					console.log('没车了');
					clearInterval(timerId);
					timerId = null;
					isRun = false;
				}
				spirits.oldLength = spirits.length;
			}
			window.onload = function() {
				var c = document.getElementById("myCanvas");
				ctx = c.getContext("2d");
			}

			function btnStart_click() {
				isRun = !isRun;
				if (timerId) {
					return;
				}
				initial();
				render();
				timerId = setInterval(render, 40);
			}
		</script>
	</head>
	<body>
		<div class="div-controls">
			<button class='btnStart' onclick="btnStart_click();">开始</button>
		</div>
		<canvas id="myCanvas" width="800" height="600"></canvas>
	</body>
</html>
